home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / adduser / common.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-10  |  9.3 KB  |  472 lines

  1. /* 
  2.  * common.c --
  3.  *
  4.  *    Collect infomation on a new account request.
  5.  *      Make sure the information is valid.  Then mail it
  6.  *      to the staff.
  7.  *
  8.  * Copyright 1990 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/admin/adduser/RCS/common.c,v 1.5 91/06/10 12:08:33 kupfer Exp $";
  20. #endif
  21.  
  22. #include "common.h"
  23. #include <sprite.h>
  24. #include <ctype.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/param.h>
  32. #include <sys/types.h>
  33. #include <sys/wait.h>
  34. #include <time.h>
  35. #include <unistd.h>
  36.  
  37. /* Forward references: */
  38. #if 0
  39. static void mail _ARGS_((CONST char *whom, CONST char *msg));
  40. #endif
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * raw_getchar --
  47.  *
  48.  *    Get a character in cbreak mode, without waiting for a carriage
  49.  *      return.
  50.  *
  51.  * Results:
  52.  *    Returns the character read, or EOF if no more input is available.
  53.  *
  54.  * Side effects:
  55.  *    None.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59.  
  60. int
  61. raw_getchar()
  62. {
  63.     struct sgttyb sgtty_buf;
  64.     int c;
  65.  
  66.     ioctl(fileno(stdin), TIOCGETP, &sgtty_buf);
  67.     sgtty_buf.sg_flags |= CBREAK;
  68.     ioctl(fileno(stdin), TIOCSETP, &sgtty_buf);
  69.     c = getchar();
  70.     sgtty_buf.sg_flags &= ~CBREAK;
  71.     ioctl(fileno(stdin), TIOCSETP, &sgtty_buf);
  72.     return c;
  73. }
  74.  
  75.  
  76. /*
  77.  *----------------------------------------------------------------------
  78.  *
  79.  * yes --
  80.  *
  81.  *    Get a yes/no response from the user.
  82.  *
  83.  * Results:
  84.  *    1 if the user said yes, 0 if no.
  85.  *
  86.  * Side effects:
  87.  *    None.
  88.  *
  89.  *----------------------------------------------------------------------
  90.  */
  91.  
  92. int
  93. yes(prompt)
  94.     char *prompt;
  95. {
  96.     int x;
  97.  
  98.     for (;;) {
  99.     printf("\n%s  (y or n) ", prompt);
  100.     x = raw_getchar();
  101.     printf("\n");
  102.     switch (x) {
  103.  
  104.     case 'y':
  105.     case 'Y':
  106.         x = 1;
  107.         break;
  108.  
  109.     case 'n':
  110.     case 'N':
  111.         x = 0;
  112.         break;
  113.  
  114.     default:
  115.         continue;
  116.     }
  117.     break;
  118.     }
  119.     return x;
  120. }
  121.  
  122. void
  123. getString(forbid, prompt, string)
  124.     CONST char *forbid;
  125.     CONST char *prompt;
  126.     char *string;
  127. {
  128.     char buffer[BUFFER_SIZE];
  129.     CONST char *f;
  130.  
  131.     for (;;) {
  132.     printf(string[0] ? "%s(%s): " : "%s: ", prompt, string);
  133.     fgets(buffer, BUFFER_SIZE - 1, stdin);
  134.     if (buffer[strlen(buffer) - 1] == '\n') {
  135.         buffer[strlen(buffer) - 1] = '\0';
  136.     }
  137.     if (buffer[0] != '\0') {
  138.         strcpy(string, buffer);
  139.     }
  140.     for (f = forbid;; ++f) {
  141.         if (*f == '\0') {
  142.         return;
  143.         }
  144.         if (strchr(buffer, *f)) {
  145.         fprintf(stderr, "This entry cannot contain a `%c'!\n", *f);
  146.         break;
  147.         }
  148.     }
  149.     }
  150. }
  151.  
  152. void
  153. getPasswd(p)
  154.     char *p;
  155. {
  156.     char passwd1[BUFFER_SIZE];
  157.     char passwd2[BUFFER_SIZE];
  158.     static char salt_chars[] = 
  159.       "./abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  160.     static char salt[3];
  161.     int c;
  162.     struct sgttyb sgtty_buf;
  163.  
  164.     printf("Press 1 to enter an encrypted passwd\n");
  165.     printf("Press 2 to enter a plaintext passwd\n");
  166.     printf("Press 3 to leave this field blank\n");
  167.     for (;;) {
  168.     printf("Please enter 1, 2 or 3: ");
  169.     c = raw_getchar();
  170.     printf("\n");
  171.     switch (c) {
  172.  
  173.     case '1':
  174.         getString("", "Enter encrypted passwd", p);
  175.         if ((strlen(p) != 13) || strspn(p, salt_chars) != 13) {
  176.         printf("%s is not a valid encrypted password!\n", passwd1);
  177.         printf("Please try again.\n");
  178.         continue;
  179.         }
  180.         return;
  181.  
  182.     case '2':
  183.         passwd1[0] = '\0';
  184.         passwd2[0] = '\0';
  185.         ioctl(0, TIOCGETP, &sgtty_buf);
  186.         sgtty_buf.sg_flags &= ~ECHO;
  187.         ioctl(0, TIOCSETP, &sgtty_buf);
  188.         getString("", "Password", passwd1);
  189.         printf("\n");
  190.         getString("", "Retype passwd", passwd2);
  191.         printf("\n");
  192.         if (*passwd1 == '\0' || strcmp(passwd1, passwd2) != 0) {
  193.         printf("Sorry, try again\n");
  194.         continue;
  195.         }
  196.         sgtty_buf.sg_flags |= ECHO;
  197.         ioctl(0, TIOCSETP, &sgtty_buf);
  198.         srandom(time(0));
  199.         salt[0] = salt_chars[random() % sizeof(salt_chars)];
  200.         salt[1] = salt_chars[random() % sizeof(salt_chars)];
  201.         strcpy(p, crypt(passwd1, salt));
  202.         return;
  203.  
  204.     case '3':
  205.         strcpy(p, "*");
  206.         return;
  207.  
  208.     default:
  209.         continue;
  210.     }
  211.     }
  212. }
  213.  
  214. char *
  215. getShell()
  216. {
  217.     int c;
  218.  
  219.     printf("Please select a shell\n");
  220.     printf("\t1  csh (default)\n");
  221.     printf("\t2  tcsh\n");
  222.     printf("\t3  sh\n");
  223.     for (;;) {
  224.     printf("Please enter 1, 2 or 3: ");
  225.     c = raw_getchar();
  226.     printf("\n");
  227.     switch (c) {
  228.  
  229.     case '1':
  230.     case '\n':
  231.         return "/sprite/cmds/csh";
  232.  
  233.     case '2':
  234.         return "/sprite/cmds/tcsh";
  235.  
  236.     case '3':
  237.         return "/sprite/cmds/sh";
  238.  
  239.     default:
  240.         continue;
  241.     }
  242.     }
  243. }
  244.  
  245. #if 0
  246. static void
  247. mail(whom, msg)
  248.     CONST char *whom;
  249.     CONST char *msg;
  250. {
  251.     int pipeFd[2];
  252.     int childPid;
  253.     int w;
  254.  
  255.     pipe(pipeFd);
  256.     switch (childPid = fork()) {
  257.  
  258.     case -1:
  259.     fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
  260.     exit(1);
  261.  
  262.     case 0: /* child */
  263.     close(pipeFd[1]);
  264.     dup2(pipeFd[0], 0);
  265.     execlp("mail", "mail", whom, NULL);
  266.     fprintf(stderr, "Can't exec mail: %s\n", strerror(errno));
  267.     exit(1);
  268.  
  269.     default: /* parent */
  270.         close(pipeFd[0]);
  271.     if (write(pipeFd[1], msg, strlen(msg)) != strlen(msg)) {
  272.         fprintf(stderr, "Error writing to pipe: %s\n", strerror(errno));
  273.         exit(1);
  274.     }
  275.     close(pipeFd[1]);
  276.     while ((w = wait(0)) > 0 && w != childPid) {
  277.         continue;
  278.     }
  279.     printf("done sending mail\n");
  280.     break;
  281.     }
  282.     return;
  283. }
  284. #endif /* 0 */
  285.  
  286. void
  287. getNumber(prompt, buf)
  288.     CONST char *prompt;
  289.     char *buf;
  290. {
  291.  
  292.     for (;;) {
  293.     getString("", prompt, buf);
  294.     if (checkNumber(buf)) {
  295.         return;
  296.     }
  297.     fprintf(stderr, "Only digits [0-9] should be used!\n");
  298.     *buf = '\0';
  299.     }
  300. }
  301.  
  302. int
  303. checkNumber(buf)
  304.     char *buf;
  305. {
  306.     int i;
  307.  
  308.     for (i = strlen(buf); --i >= 0;) {
  309.     if (!isascii(buf[i]) || !isdigit(buf[i])) {
  310.         return 0;
  311.     }
  312.     }
  313.     return 1;
  314. }
  315.  
  316.  
  317. /*
  318.  *----------------------------------------------------------------------
  319.  *
  320.  * makedb --
  321.  *
  322.  *    Regenerate the hashed password file.
  323.  *
  324.  * Results:
  325.  *    0 for success, an exit status otherwise.
  326.  *
  327.  * Side effects:
  328.  *    Creates the .dir and .pag files to match the plain-text 
  329.  *    password file.
  330.  *
  331.  *----------------------------------------------------------------------
  332.  */
  333.  
  334. int
  335. makedb(file)
  336.     char *file;
  337. {
  338.     int status, pid, w;
  339.     
  340.     if (!(pid = vfork())) {
  341.     execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL);
  342.     (void) fprintf(stderr, "Can't exec %s: %s\n",
  343.                _PATH_MKPASSWD, strerror(errno));
  344.     _exit(127);
  345.     }
  346.     while ((w = wait(&status)) != pid && w != -1) {
  347.     continue;
  348.     }
  349.     return(w == -1 || status);
  350. }
  351.  
  352.  
  353. /*
  354.  *----------------------------------------------------------------------
  355.  *
  356.  * rcsCheckOut --
  357.  *
  358.  *    Check out a file.
  359.  *
  360.  * Results:
  361.  *    Returns the exit status of the "co" invocation, or -1 if there 
  362.  *    was a system error (and co couldn't be run).
  363.  *
  364.  * Side effects:
  365.  *    Checks out the file.
  366.  *
  367.  *----------------------------------------------------------------------
  368.  */
  369. int
  370. rcsCheckOut(file)
  371.     char *file;
  372. {
  373.     int child;
  374.     union wait ws;
  375.     int w;
  376.  
  377.     switch (child = fork()) {
  378.  
  379.     case -1:
  380.     fprintf(stderr, "Fork failed: %s\n", strerror(errno));
  381.     return -1;
  382.     case 0:
  383.     execlp("co", "co", "-l", file, NULL);
  384.     fprintf(stderr, "Cannot exec co: %s\n", strerror(errno));
  385.     exit(EXIT_FAILURE);
  386.     default:
  387.     while ((w = wait(&ws)) > 0 && w != child) {
  388.         continue;
  389.     }
  390.     return ws.w_retcode;
  391.     }
  392. }
  393.  
  394.  
  395. /*
  396.  *----------------------------------------------------------------------
  397.  *
  398.  * rcsCheckIn --
  399.  *
  400.  *    Check in a file.
  401.  *
  402.  * Results:
  403.  *    Returns the exit code of the "ci" invocation, or -1 if there 
  404.  *    was a system error (and ci couldn't be run).
  405.  *
  406.  * Side effects:
  407.  *    Checks in the file, whether or not it had actually changed.
  408.  *
  409.  *----------------------------------------------------------------------
  410.  */
  411. int
  412. rcsCheckIn(file, logMsg)
  413.     char *file;            /* file to check in */
  414.     char *logMsg;        /* message for the RCS log, with 
  415.                  * leading -m */
  416. {
  417.     int child;
  418.     union wait ws;
  419.     int w;
  420.  
  421.     switch (child = fork()) {
  422.     case -1:
  423.     fprintf(stderr, "Fork failed: %s\n", strerror(errno));
  424.     return -1;
  425.     case 0:
  426.     dup2(open("/dev/null", O_RDONLY), 0);
  427.     execlp("ci", "ci", logMsg, "-f", "-u", file, NULL);
  428.     fprintf(stderr, "Cannot exec ci: %s\n", strerror(errno));
  429.     exit(EXIT_FAILURE);
  430.     default:
  431.     while ((w = wait(&ws)) > 0 && w != child) {
  432.         continue;
  433.     }
  434.     return ws.w_retcode;
  435.     }
  436. }
  437.  
  438.  
  439. /*
  440.  *----------------------------------------------------------------------
  441.  *
  442.  * SecurityCheck --
  443.  *
  444.  *    Verify that we're running as root.  Make the real ID and 
  445.  *    effective ID both be root.
  446.  *    
  447.  *    The real ID is made root to avoid problems with subprocesses 
  448.  *    that exec random programs and act differently if the effective 
  449.  *    ID is different from the real ID.  This is not a security 
  450.  *    problem, because the program is installed so that only root or 
  451.  *    wheels can run it.
  452.  *
  453.  * Results:
  454.  *    None.
  455.  *
  456.  * Side effects:
  457.  *    Exits if any of the checks fail.
  458.  *
  459.  *----------------------------------------------------------------------
  460.  */
  461.  
  462. void
  463. SecurityCheck()
  464. {
  465.     if (setreuid(0, 0) < 0) {
  466.     perror("Can't setuid to root");
  467.     fprintf(stderr,
  468.         "Check whether the program was correctly installed.\n");
  469.     exit(EXIT_FAILURE);
  470.     }
  471. }
  472.